package com.dq.redis.jedispool;

import com.alibaba.fastjson.JSON;
import com.dq.utils.gsonutils.GsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @author cf
 */
@Component
public class JedisUtils {

    @Autowired
    private JedisPoolMyConfig jedisPoolMyConfig;

    private static ReentrantLock lockJedis = new ReentrantLock();
    private static JedisPool jedisPool = null;


    /**  默认过期时长，单位：秒 */
    public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
    /**  不设置过期时长 */
    public final static long NOT_EXPIRE = -1;

    /**
     * set string
     * @param key
     * @param value
     * @return
     */
    public synchronized String setString(String key, Object value) {
        Jedis jedis = getJedis();

        return jedis.set(key, toJson(value));
    }
    /**
     * 设置 过期时间
     *
     * @param key
     * @param seconds 以秒为单位
     * @param value
     */
    public synchronized void setString(String key, Object value, int seconds) {
        Jedis jedis = getJedis();

        jedis.setex(key, seconds, toJson(value));
    }

    /**
     * redis 发布消息(生产者)
     *
     * @param channel 频道
     * @param message 信息
     * @return
     */
    public synchronized Long publish(String channel, String message) {
        Jedis jedis = getJedis();

        return jedis.publish(channel, message);
    }

    /**
     * get String
     *
     * @param key
     * @return
     */
    public synchronized String getString(String key) {
        Jedis jedis = getJedis();

        return jedis.get(key);
    }

    /**
     * get String
     * 可以重新设置过期时间
     *
     * @param key
     * @param seconds 以秒为单位
     * @return
     */
    public synchronized String getString(String key, int seconds) {
        Jedis jedis = getJedis();

        if(seconds > 0){
            // 重新设置过期时间
            jedis.expire(key, seconds);
        }

        return jedis.get(key);
    }

    /**
     * get 实体
     *
     * @param key
     * @param clazz 以秒为单位
     * @param <T>
     * @return
     */
    public synchronized <T> T getClass(String key, Class<T> clazz) {
        String value = getString(key);

        return value == null ? null : fromJson(value, clazz);
    }
    /**
     * get 实体
     * 可以重新设置过期时间
     *
     * @param key
     * @param clazz
     * @param seconds
     * @param <T>
     * @return
     */
    public synchronized <T> T getClass(String key, Class<T> clazz, int seconds) {
        Jedis jedis = getJedis();

        String value = getString(key);
        if(seconds > 0){
            // 重新设置过期时间
            jedis.expire(key, seconds);
        }
        return value == null ? null : fromJson(value, clazz);
    }

    public synchronized void delete(String key) {
        Jedis jedis = getJedis();

        jedis.del(key);
    }

    /**
     * Object转成JSON数据
     */
    private String toJson(Object object){
        if(object instanceof Integer || object instanceof Long || object instanceof Float ||
                object instanceof Double || object instanceof Boolean || object instanceof String){
            return String.valueOf(object);
        }
        return JSON.toJSONString(object);
    }

    /**
     * JSON数据，转成Object
     */
    private <T> T fromJson(String json, Class<T> clazz){
        GsonUtils.getDateGson().fromJson(json, clazz);
        return JSON.parseObject(json, clazz);
    }



    /**
     * 加锁, 获取redis实例
     */
    private Jedis getJedis() {
        // 尝试获取redis实例锁，适用于高并发多线程场景
        lockJedis.lock();
        Jedis jedis = null;
        try {
            if (jedisPool == null) {
                jedisPool = jedisPoolMyConfig.getJedisPool();
            }
            jedis = jedisPool.getResource();

            // 开启失效监听
            jedis.configSet("notify-keyspace-events", "Ex");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放jedis资源, 回收之后的连接，依然可以继续使用,可以查看源码
            closeJedis(jedis);
            // 释放锁
            lockJedis.unlock();
        }

        return jedis;
    }
    /**
     * 释放jedis资源
     */
    public void closeJedis(Jedis jedis) {
        ///
//        if (jedis != null && jedisPool != null) {
//            // returnResource弃用
//            jedisPool.returnResource(jedis);
//        }

        if (jedis != null) {
            jedis.close();
        }
    }

}
